@file:Suppress("unused")

package xyz.scootaloo.kami.server.model

import xyz.scootaloo.kami.server.standard.AccessDeniedException
import xyz.scootaloo.kami.server.service.Constant.GUEST

/**
 *
 * @author flutterdash@qq.com
 * @since 2022/1/8 23:37
 */

typealias UPKey = UserPrincipalKey

fun AccessToken.uid(): Int {
    return if (this is UserAccessToken) this.uid
    else UserAccessToken.defUid
}

fun accessDenied(type: AccessType): AccessDeniedException = when (type.key) {
    0 -> ex_access
    1 -> ex_download
    2 -> ex_modify
    else -> ex_define
}

private val ex_access = AccessDeniedException(AccessType.ACCESS)
private val ex_download = AccessDeniedException(AccessType.DOWNLOAD)
private val ex_modify = AccessDeniedException(AccessType.MODIFY)
private val ex_define = AccessDeniedException(AccessType.DEFINE)

operator fun AccessToken.plus(type: AccessType): AccessToken {
    this.types.add(type)
    return this
}

/**
 * 用户要访问文件系统, 例如查看文件信息, 下载文件, 上传文件, 查看目录内容等操作时,
 * 需要先进入权限系统检查用户是否有对应的权限, 而权限系统检查的项目包括以下几条
 *
 * - path 此操作对应的文件系统的路径
 * - type 操作类型
 * - level 用户的等级, 这个等级帮助权限系统忽略一些低级的限制加快检查速度
 *
 * 举个例子, 一个未登录的用户要查看目录`/home`下的内容, 那么应该这样构造对象
 *
 * ```kotlin
 * AccessToken(
 *     path = "home",
 *     level = AccessLevel.GUEST,
 *     type = AccessType.ACCESS
 * )
 * ```
 */
open class AccessToken(
    val path: String,
    val level: Int,
    var types: MutableList<AccessType> = ArrayList(1),
)

class UserAccessToken(
    val uid: Int,
    path: String,
    level: Int
) : AccessToken(path, level) {
    companion object {
        const val defUid = 0
    }
}


enum class AccessType(val key: Int) {

    /**
     * 访问权限: 进入目录, 查看目录内容, 查看文件信息, 预览文件内容
     */
    ACCESS(0),

    /**
     * 下载权限: 下载文件
     */
    DOWNLOAD(1),

    /**
     * 修改权限: 创建文件, 创建目录, 上传文件
     * 修改文件内容, 移动/删除/复制文件或目录, 重命名;
     */
    MODIFY(2),

    /**
     * 定义权限: 对规则的设定和删除
     */
    DEFINE(3)

}

/**
 *
 * @author flutterdash@qq.com
 * @since 2022/2/1 11:44
 */
object AccessLevel {
    /**
     * 未登录用户具备此权限
     */
    const val GUEST = 0

    /**
     * 登录后具备此权限
     */
    const val USER = 1

    /**
     * 向超级管理员申请并通过后得到此权限
     */
    const val ADMIN = 2

    /**
     * 系统部署后, 输入正确的口令后得到此权限;
     * 一个系统中只有一个超级管理员;
     */
    const val SUPER_ADMIN = 3
}

/**
 * 定位一个用户, 当用户登录或者注册成功后, 系统会为用户签发一个jwt,
 * 其中jwt中的载体就是这个类
 *
 * @param id 用户在数据库中存储时指定的唯一ID
 * @param username 用户名
 * @param role 用户的角色, 也是用户的等级
 */
data class UserPrincipal(
    val id: Int,
    val username: String,
    val role: Int
)

enum class UserPrincipalKey(
    val key: String, val defValue: Any
) {
    ID("id", -1),
    USERNAME("username", GUEST),
    ROLE("role", AccessLevel.GUEST)
}